package cn.itsource.basic.base.service.impl;

import cn.itsource.basic.base.service.ILoginService;
import cn.itsource.basic.constant.WechatConstant;
import cn.itsource.basic.exception.CustomException;
import cn.itsource.basic.exception.ErrorCode;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.HttpClientUtils;
import cn.itsource.basic.util.MD5Utils;
import cn.itsource.basic.util.StrUtils;
import cn.itsource.jwt.JwtUtils;
import cn.itsource.jwt.PayloadData;
import cn.itsource.jwt.RsaUtils;
import cn.itsource.org.domain.Logininfo;
import cn.itsource.org.domain.User;
import cn.itsource.org.domain.Wxuser;
import cn.itsource.org.mapper.LogininfoMapper;
import cn.itsource.org.mapper.UserMapper;
import cn.itsource.org.mapper.WxuserMapper;
import cn.itsource.org.service.impl.UserServiceImpl;
import cn.itsource.system.domain.Menu;
import cn.itsource.system.mapper.MenuMapper;
import cn.itsource.system.mapper.PermissionMapper;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.PrivateKey;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {

    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WxuserMapper wxuserMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;


    @Override
    public AjaxResult accountLogin(Map<String, Object> map) throws Exception {
        //取数据
        String username = map.get("username").toString();
        String password = map.get("password").toString();
        Integer type = Integer.valueOf(map.get("type").toString());
        //查询用户
        Logininfo lf = logininfoMapper.loadByUsername(username,type);
        //判断使用是否存在
        if(lf == null){
            throw new CustomException(ErrorCode.ACCOUNT_OR_PWD_ERROR.getCode());
        }
        //判断密码
        String salt = lf.getSalt();
        String inputPwd = MD5Utils.encrypByMd5(password + salt);
        if(!inputPwd.equals(lf.getPassword())){
            throw new CustomException(ErrorCode.ACCOUNT_OR_PWD_ERROR.getCode());
        }
//        //存储redis key是uuid value就是用户信息
//        String redisKey = UUID.randomUUID().toString();
//        redisTemplate.opsForValue().set(redisKey,lf,30, TimeUnit.MINUTES);
//
//        //返回 用户信息和token
//        lf.setPassword(null);
//        lf.setSalt(null);
//        lf.setDisable(null);
//        HashMap<String, Object> result = new HashMap<>();
//        result.put("token",redisKey);
//        result.put("loginInfo",lf);

        return loginService(lf);
    }

    @Override
    public AjaxResult wechatLogin(Map<String, String> map) throws Exception {
        //把code取出来
        String code = map.get("code");
        //构建获取openid和token的请求
        String url = WechatConstant.GET_TOKEN.replace("APPID", WechatConstant.APPID)
                .replace("SECRET", WechatConstant.SECRET)
                .replace("CODE", code);
        //发送请求获取token和openid
        String result = HttpClientUtils.httpGet(url);
        //把结果转成json对象
        JSONObject resultObject = JSONObject.parseObject(result);
        //从结果对象中取出openid和token
        String token = resultObject.getString("access_token");
        String openid = resultObject.getString("openid");
        //先使用openid去查询数据库中该用户是否已经绑定了微信
        Logininfo lf = logininfoMapper.loadByOpenid(openid);
        //判断用户是否存在
        if(lf != null){
            return loginService(lf);
        }else {
            //如果没有用户，门户站要跳转绑定页面，并且url后携带token和openid   xxxx.binder.html?openid=xxx&token=xxx
            String binderUrl = "?openid="+openid+"&token="+token;
            return AjaxResult.me().setSuccess(false).setCode(401).setResultObj(binderUrl);
        }


    }

    private AjaxResult loginService(Logininfo lf) throws Exception {
        //免密登录
        //存储redis key是uuid value就是用户信息
//        String redisKey = UUID.randomUUID().toString();
//        redisTemplate.opsForValue().set(redisKey, lf,30, TimeUnit.MINUTES);

        //查询用户的permissions
        List<String> permissions = permissionMapper.loadByLoginInfoId(lf.getId());
        //查询用户的menus
        List<Menu> menus = menuMapper.loadByLoginInfoId(lf.getId());
        //创建加密对象
        PayloadData data = new PayloadData();
        data.setLogininfo(lf);
        data.setPermissions(permissions);
        data.setMenus(menus);
        //加密得到jwt token
        PrivateKey privateKey = RsaUtils.getPrivateKey(JwtUtils.class.getClassLoader().getResource("hrm_auth_rsa").getFile());
        String token = JwtUtils.generateTokenExpireInMinutes(data, privateKey, 60*24);
        //返回 用户信息和token
        lf.setPassword(null);
        lf.setSalt(null);
        lf.setDisable(null);
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("token",token);
        resultMap.put("loginInfo", lf);
        resultMap.put("permissions", permissions);
        resultMap.put("menus", menus);
        return AjaxResult.me().setResultObj(resultMap);
    }

    @Override
    @Transactional
    public AjaxResult binder(Map<String, String> map) throws Exception {
        //取参数
        String phone = map.get("phone");
        String password = map.get("password");
        String openid = map.get("openid");
        String token = map.get("token");
        //查询用户是否存在
        Logininfo lf = logininfoMapper.loadByUsername(phone, 1);
        //要注册用户已存在结束绑定流程
        if(lf != null){
            throw  new CustomException(ErrorCode.USER_ALREADY_EXIST.getCode());
        }
        //请求微信接口获取用户微信基本信息
        String userInfoUrl = WechatConstant.GET_USER_INFO.replace("ACCESS_TOKEN",token)
                .replace("OPENID",openid);
        String s = HttpClientUtils.httpGet(userInfoUrl);
        //结果集转成json对象
        JSONObject jo = JSONObject.parseObject(s);
        //密码加密
        String salt = StrUtils.getComplexRandomString(64);
        String pwd = MD5Utils.encrypByMd5(password + salt);
        //构建wxuser对象
        Wxuser wxuser = new Wxuser();
        wxuser.setOpenid(jo.getString("openid"));
        //构建user对象
        User user = UserServiceImpl.innitUser(phone, salt, pwd);
        //构建logininfo对象
        Logininfo logininfo = UserServiceImpl.user2Logininfo(user);
        //先保存logininfo，再保存user，再保存wxuser
        logininfoMapper.insert(logininfo);
        user.setLogininfoId(logininfo.getId());
        userMapper.insert(user);
        wxuser.setUserId(user.getId());
        wxuserMapper.insert(wxuser);
        //免密登录
        return loginService(logininfo);
    }

}
